home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume13 / rolodex / part03 < prev    next >
Encoding:
Internet Message Format  |  1988-01-30  |  53.8 KB

  1. Subject:  v13i051:  Screen-oriented rolodex program, Part03/04
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Dave Ihnat <ihnp4!homebru!ignatz>
  7. Posting-number: Volume 13, Issue 51
  8. Archive-name: rolodex/part03
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of archive 3 (of 4)."
  17. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  18. if test -f './io.c' -a "${1}" != "-c" ; then 
  19.   echo shar: Will not clobber existing file \"'./io.c'\"
  20. else
  21. echo shar: Extracting \"'./io.c'\" \(10740 characters\)
  22. sed "s/^X//" >'./io.c' <<'END_OF_FILE'
  23. X/* io.c */
  24. X#include <stdio.h>
  25. X#ifdef UNIX
  26. X#include <sys/types.h>
  27. X#include <sys/stat.h>
  28. X#ifdef BSD
  29. X#include <sys/file.h>
  30. X#else
  31. X#include <fcntl.h>
  32. X#endif
  33. X#endif
  34. X
  35. X#ifdef VMS
  36. X#include <types.h>
  37. X#include <stat.h>
  38. X#include <file.h>
  39. X#endif
  40. X
  41. X#ifdef MSDOS
  42. X#    ifdef MSC
  43. X#    include <sys/types.h>
  44. X#    endif    /* MSC */
  45. X#include <sys/stat.h>
  46. X#include <fcntl.h>
  47. X#endif
  48. X
  49. X#include <ctype.h>
  50. X
  51. X#ifdef TMC
  52. X#include <ctools.h>
  53. X#else
  54. X#include "ctools.h"
  55. X#endif
  56. X
  57. X#include "rolofilz.h"
  58. X#include "datadef.h"
  59. X
  60. X
  61. Xchar *Field_Names[N_BASIC_FIELDS] = {
  62. X        
  63. X        "Name: ", "Work Phone: ", "Home Phone: ", "Company: ",
  64. X        "Work Address: ", "Home Address: ", "Remarks: ", "Date Updated: "
  65. X        
  66. X     };
  67. X
  68. XPtr_Rolo_List Begin_Rlist = 0;
  69. XPtr_Rolo_List End_Rlist = 0;
  70. XPtr_Rolo_List Current_Entry = 0;
  71. X
  72. Xstatic char *rolofiledata;
  73. X
  74. X/*
  75. X * The following has been added to accomplish two goals:
  76. X *
  77. X * 1)  Document all help files expected in the system, to avoid/identify
  78. X *     lost elements in distribution.
  79. X *
  80. X * 2)  Allow a flexible, easily-modified way of changing filenames as
  81. X *     necessary/desired to comply with different operating systems.
  82. X */
  83. Xchar *hlpfiles[] = {
  84. X    "addhelp.hlp",    /* ADDHELP        */
  85. X    "addinfo.hlp",    /* ADDINFO        */
  86. X    "confirm.hlp",    /* CONFIRMHELP        */
  87. X    "entrymnu.hlp",    /* ENTRYMENU        */
  88. X    "escan.hlp",    /* ESCANHELP        */
  89. X    "esearch.hlp",    /* ESEARCHHELP          */
  90. X    "fldsrch.hlp",    /* FIELDSEARCHHELP      */
  91. X#ifdef UNIX
  92. X    "lockinfo.unx",    /* LOCKINFO            */
  93. X#endif
  94. X#ifdef VMS
  95. X    "lockinfo.vms",    /* LOCKINFO            */
  96. X#endif
  97. X#ifdef MSDOS
  98. X    "lockinfo.dos",    /* LOCKINFO            */
  99. X#endif
  100. X    "mainmenu.hlp",    /* MAINMENU        */
  101. X    "mnymtch.hlp",    /* MANYMATCHHELP         */
  102. X    "moption.hlp",    /* MOPTIONHELP            */
  103. X    "moptions.hlp",    /* MOPTIONSHELP            */
  104. X    "moreflds.hlp",    /* MOREFIELDSHELP        */
  105. X    "newadd.hlp",    /* NEWADDHELP             */
  106. X    "otherfmt.hlp",    /* OTHERFORMATHELP     */
  107. X    "pkentry.hlp",    /* PICKENTRYHELP         */
  108. X    "pkntmenu.hlp",    /* PICKENTRYMENU    */
  109. X    "poptmenu.hlp",    /* POPTIONMENU             */
  110. X    "poptions.hlp",    /* POPTIONSHELP             */
  111. X    "srchstr.hlp",    /* SEARCHSTRINGHELP      */
  112. X    "update.hlp",    /* UPDATEHELP            */
  113. X    "updatmnu.hlp",    /* UPDATEMENU           */
  114. X    "usrfld.hlp",    /* USERFIELDHELP         */
  115. X};
  116. X
  117. X
  118. Xread_rolodex (fd) int fd;
  119. X                                             
  120. X{
  121. X  struct stat statdata;
  122. X  long filesize;
  123. X  int i,j,k,start_of_others,warning_given;
  124. X  Ptr_Rolo_Entry newentry;
  125. X  Ptr_Rolo_List newlink,rptr;
  126. X  char *next_field,*next_other;
  127. X  char **other_pointers;
  128. X  int n_entries = 0;
  129. X
  130. X  /* find out how many bytes are in the file */
  131. X
  132. X  fstat(fd,&statdata);
  133. X  if ((filesize = statdata.st_size) == 0) {
  134. X     return(0);
  135. X  }
  136. X
  137. X  /* create an array of characters that big */
  138. X  
  139. X  rolofiledata = rolo_emalloc(filesize);
  140. X
  141. X  /* read them all in at once for efficiency */
  142. X  
  143. X#ifdef MSDOS
  144. X  /*
  145. X   * Unlike Unix, MS-DOS compilers make a distinction between text and
  146. X   * binary files.  Unfortunately, this means that in text mode, the file
  147. X   * size is reported by the stat call won't necessarily match the value
  148. X   * reported by the read, since there is CR/LF character translation.
  149. X   * So, the best we can hope for here is that a failed read will give a
  150. X   * zero or negative return value...
  151. X   */
  152. X  if ((filesize = read(fd,rolofiledata,filesize)) <= 0) {
  153. X#else
  154. X  if (filesize != read(fd,rolofiledata,filesize)) {
  155. X#endif
  156. X     fprintf(stderr,"rolodex read failed\n");
  157. X     exit(-1);
  158. X  }
  159. X
  160. X  j = 0;
  161. X  
  162. X  /* for each entry in the rolodex file */
  163. X  
  164. X  while (j < filesize) {
  165. X
  166. X      n_entries++;
  167. X        
  168. X      /* create the link and space for the data entry */
  169. X        
  170. X      newlink = new_link_with_entry();
  171. X      newentry = get_entry(newlink);
  172. X      if (j == 0) {
  173. X         Begin_Rlist = newlink;
  174. X         set_prev_link(newlink,0);
  175. X         set_next_link(newlink,0);
  176. X      }
  177. X      else {
  178. X          set_next_link(End_Rlist,newlink);
  179. X          set_prev_link(newlink,End_Rlist);
  180. X          set_next_link(newlink,0);
  181. X      }
  182. X      End_Rlist = newlink;
  183. X
  184. X      /* locate each required field in the character array and change */
  185. X      /* the ending line feed to a null.  Insert a pointer to the */
  186. X      /* beginning of the field into the data entry */
  187. X
  188. X      for (i = 0; i < N_BASIC_FIELDS; i++) {
  189. X          next_field = rolofiledata + j;
  190. X          while (rolofiledata[j] != '\n') {
  191. X            j++;
  192. X          }
  193. X          rolofiledata[j] = '\0';
  194. X          j++;
  195. X          set_basic_rolo_field(i,newentry,next_field);
  196. X      }
  197. X
  198. X      /* the end of an entry is indicated by two adjacent newlines */
  199. X
  200. X      if (rolofiledata[j] == '\n') {
  201. X         j++;
  202. X         newentry -> other_fields = 0;
  203. X         continue;
  204. X      }
  205. X
  206. X      /* there must be additional, user-inserted fields. Find out how many. */
  207. X
  208. X      start_of_others = j;
  209. X      while (1) {
  210. X        while (rolofiledata[j] != '\n') {
  211. X          j++;
  212. X        }
  213. X        incr_n_others(newentry);
  214. X        j++;
  215. X        if (rolofiledata[j] == '\n') {
  216. X           j++;
  217. X           break;
  218. X        }
  219. X     }
  220. X
  221. X     /* allocate an array of character pointers to hold these fields */
  222. X
  223. X     other_pointers = (char **)rolo_emalloc(get_n_others(newentry)*sizeof(char *));
  224. X
  225. X     /* separate each field and insert a pointer to it in the char array */
  226. X
  227. X     k = start_of_others;
  228. X     for (i = 0; i < get_n_others(newentry); i++) {
  229. X         next_other = rolofiledata + k;
  230. X         while (rolofiledata[k] != '\n') {
  231. X           k++;
  232. X         }
  233. X         rolofiledata[k] = '\0';
  234. X         other_pointers[i] = next_other;
  235. X         k++;
  236. X     }
  237. X
  238. X     /* insert the pointer to this character array into the data entry */
  239. X
  240. X     newentry -> other_fields = other_pointers;
  241. X
  242. X  }
  243. X
  244. X  /* check that all the entries are in alphabetical order by name */
  245. X  
  246. X  warning_given = 0;
  247. X  rptr = get_next_link(Begin_Rlist);
  248. X  while (rptr != 0) {
  249. X    if (1 == compare_links(get_prev_link(rptr),rptr)) {
  250. X       if (!warning_given) fprintf(stderr,"Warning, rolodex out of order\n");
  251. X       warning_given = 1;
  252. X       reorder_file = 1;
  253. X    }
  254. X    rptr = get_next_link(rptr);
  255. X  }    
  256. X    
  257. X  return(n_entries);
  258. X  
  259. X}
  260. X
  261. X
  262. Xwrite_rolo_list (fp) FILE *fp; 
  263. X
  264. X/* write the entire in-core rolodex to a file */
  265. X
  266. X{
  267. X
  268. X  Ptr_Rolo_List rptr;
  269. X  Ptr_Rolo_Entry lentry;
  270. X  int j;
  271. X
  272. X  rptr = Begin_Rlist;
  273. X
  274. X  while (rptr != 0) {
  275. X    lentry = get_entry(rptr);
  276. X    for (j = 0; j < N_BASIC_FIELDS; j++) {
  277. X        fprintf(fp,"%s\n",get_basic_rolo_field(j,lentry));
  278. X    }
  279. X    for (j = 0; j < get_n_others(lentry); j++) {
  280. X        fprintf(fp,"%s\n",get_other_field(j,lentry));
  281. X    }
  282. X    fprintf(fp,"\n");
  283. X    rptr = get_next_link(rptr);
  284. X  }
  285. X
  286. X}
  287. X
  288. X
  289. Xwrite_rolo (fp1,fp2) FILE *fp1; FILE *fp2;
  290. X
  291. X{
  292. X  write_rolo_list(fp1);
  293. X  write_rolo_list(fp2);
  294. X}
  295. X
  296. X
  297. Xdisplay_basic_field (name,value,show,up) char *name; char *value; int show,up;
  298. X{
  299. X  int i;
  300. X  if ((value == (char *)NULL) || (all_whitespace(value) && !show)) return;
  301. X  printf("%-25s",name);
  302. X  while (*value != '\0') {
  303. X    if (*value == ';') {
  304. X       while (*++value == ' '); 
  305. X       putchar('\n');
  306. X       for (i = 0; i < (up ? 28 : 25); i++) putchar(' ');
  307. X    }
  308. X    else {
  309. X       putchar(*value++);
  310. X    }
  311. X  }
  312. X  putchar('\n');
  313. X}
  314. X
  315. X
  316. Xdisplay_other_field (fieldstring) char *fieldstring;
  317. X{
  318. X  int already_put_sep = 0;        
  319. X  int count = 0;
  320. X  int i;
  321. X  while (*fieldstring != '\0') {
  322. X    if (*fieldstring == ';' && already_put_sep) {
  323. X       while (*++fieldstring == ' ');
  324. X       putchar('\n');
  325. X       for (i = 0; i < 25; i++) putchar(' ');
  326. X       continue;
  327. X    }
  328. X    putchar(*fieldstring);
  329. X    count++;
  330. X    if (*fieldstring == ':' && !already_put_sep) {
  331. X       for (i = count; i < 24; i++) putchar(' ');
  332. X       already_put_sep = 1;
  333. X    }
  334. X    fieldstring++;
  335. X  }
  336. X  putchar('\n');
  337. X}
  338. X
  339. X
  340. Xsummarize_entry_list (rlist,ss) Ptr_Rolo_List rlist; char *ss;
  341. X
  342. X/* print out the Name field for each entry that is tagged as matched */
  343. X/* and number each entry. */
  344. X
  345. X{
  346. X  int count = 1;
  347. X  clear_the_screen();
  348. X  printf("Entries that match '%s' :\n\n",ss);
  349. X  while (rlist != 0) {
  350. X    if (get_matched(rlist)) {
  351. X       printf (
  352. X          "%d. \t%s\n",
  353. X          count++,
  354. X          get_basic_rolo_field((int) R_NAME,get_entry(rlist))
  355. X       );
  356. X    }
  357. X    rlist = get_next_link(rlist);    
  358. X  }
  359. X  putchar('\n');
  360. X}
  361. X
  362. X
  363. Xdisplay_field_names ()
  364. X
  365. X/* display and number each standard field name. */
  366. X
  367. X{
  368. X  int j;
  369. X  char *name;
  370. X  clear_the_screen();
  371. X  for (j = 0; j < N_BASIC_FIELDS - 1; j++) {        
  372. X      name = Field_Names[j];        
  373. X      printf("%d. ",j+1);
  374. X      while (*name != ':') putchar(*name++);
  375. X      putchar('\n');
  376. X  }
  377. X  printf("%d. ",N_BASIC_FIELDS);
  378. X  printf("A user created item name\n\n");
  379. X}  
  380. X  
  381. Xdisplay_entry (lentry) Ptr_Rolo_Entry lentry;
  382. X{
  383. X  int j,n_others;
  384. X  char *string;
  385. X  
  386. X  clear_the_screen();
  387. X  
  388. X  /* display the standard fields other than Date Updated */
  389. X  
  390. X  for (j = 0; j < N_BASIC_FIELDS - 1; j++) {
  391. X      string = get_basic_rolo_field(j,lentry);
  392. X      display_basic_field(Field_Names[j],string,0,0);
  393. X  }        
  394. X      
  395. X  /* display any additional fields the user has defined for this entry */
  396. X  
  397. X  n_others = get_n_others(lentry);
  398. X  for (j = 0; j < n_others; j++) {
  399. X      string = get_other_field(j,lentry);
  400. X      display_other_field(string);
  401. X   }
  402. X
  403. X   /* display the Date Updated field */
  404. X   
  405. X   j = N_BASIC_FIELDS - 1;
  406. X   display_basic_field(Field_Names[j],get_basic_rolo_field(j,lentry),0,0);
  407. X   fprintf(stdout,"\n");
  408. X
  409. X}
  410. X
  411. X
  412. Xdisplay_entry_for_update (lentry) Ptr_Rolo_Entry lentry;
  413. X
  414. X/* same as display_entry, except each item is numbered and the Date Updated */
  415. X/* item is not displayed */
  416. X
  417. X{
  418. X  int j,n_others;
  419. X  char *string;
  420. X  int count = 1;
  421. X  
  422. X  clear_the_screen();
  423. X  
  424. X  for (j = 0; j < N_BASIC_FIELDS - 1; j++) {
  425. X      string = get_basic_rolo_field(j,lentry);
  426. X      printf("%d. ",count++);
  427. X      display_basic_field(Field_Names[j],string,1,1);
  428. X  }        
  429. X      
  430. X  n_others = get_n_others(lentry);
  431. X  for (j = 0; j < n_others; j++) {
  432. X      string = get_other_field(j,lentry);
  433. X      printf("%d. ",count++);
  434. X      display_other_field(string);
  435. X  }
  436. X  
  437. X  printf("%d. Add a new user defined field\n",count);
  438. X
  439. X  fprintf(stdout,"\n");
  440. X
  441. X}
  442. X
  443. X
  444. Xint cathelpfile (fileidx,helptopic,clear)
  445. X
  446. X  int fileidx;
  447. X  char *helptopic; 
  448. X  int clear;
  449. X
  450. X{
  451. X  register char *filepath;
  452. X  FILE *fp;
  453. X  char buffer[MAXLINELEN];
  454. X
  455. X  if(fileidx > LAST_HELP) {
  456. X    fprintf(stderr,
  457. X        "INTERNAL ERROR:  Error file index, max: %d, requested: %d\n",
  458. X        LAST_HELP,fileidx);
  459. X    return;
  460. X  }else
  461. X      filepath = libdir(hlpfiles[fileidx]);
  462. X    
  463. X  if (clear) clear_the_screen();
  464. X  if (NULL == (fp = fopen(filepath,"r"))) {
  465. X     if (helptopic) {
  466. X        printf("No help available on %s, sorry.\n\n",helptopic); 
  467. X     }
  468. X     else {
  469. X        fprintf(stderr,"Fatal error, can't open %s\n",filepath);
  470. X        exit(-1);
  471. X     }
  472. X     return;
  473. X  }
  474. X  while (NULL != fgets(buffer,MAXLINELEN,fp)) printf("%s",buffer);  
  475. X  printf("\n");
  476. X  fclose(fp);
  477. X  return;
  478. X}
  479. X
  480. X
  481. Xany_char_to_continue ()
  482. X{
  483. X  char buffer[80];
  484. X  printf("RETURN to continue: ");
  485. X  fgets(buffer,80,stdin);
  486. X  return;
  487. X}
  488. END_OF_FILE
  489. if test 10740 -ne `wc -c <'./io.c'`; then
  490.     echo shar: \"'./io.c'\" unpacked with wrong size!
  491. fi
  492. # end of './io.c'
  493. fi
  494. if test -f './operatns.c' -a "${1}" != "-c" ; then 
  495.   echo shar: Will not clobber existing file \"'./operatns.c'\"
  496. else
  497. echo shar: Extracting \"'./operatns.c'\" \(9950 characters\)
  498. sed "s/^X//" >'./operatns.c' <<'END_OF_FILE'
  499. X/* operatns.c */
  500. X#include <stdio.h>
  501. X#include <ctype.h>
  502. X
  503. X#ifdef TMC
  504. X#include <ctools.h>
  505. X#else
  506. X#include "ctools.h"
  507. X#endif
  508. X#include "args.h"
  509. X#include "menu.h"
  510. X#include "mem.h"
  511. X
  512. X#include "rolofilz.h"
  513. X#include "rolodefs.h"
  514. X#include "datadef.h"
  515. X#include "choices.h"
  516. X
  517. X#define index strchr 
  518. Xchar *index();
  519. X
  520. Xextern char *ctime();
  521. X
  522. XPtr_Rolo_List create_entry (basicdata,otherdata) char **basicdata, **otherdata;
  523. X{
  524. X  Ptr_Rolo_List newlink;        
  525. X  Ptr_Rolo_Entry newentry;
  526. X  int i,j;
  527. X  newlink = new_link_with_entry();        
  528. X  newentry = get_entry(newlink);
  529. X  for (j = 0; j < N_BASIC_FIELDS; j++) {
  530. X      set_basic_rolo_field(j,newentry,basicdata[j]);
  531. X  }
  532. X  j = 0;
  533. X  while (otherdata[j] != 0) j++;
  534. X  set_n_others(newentry,j);
  535. X  if (j > 0) {
  536. X     newentry -> other_fields = (char **) rolo_emalloc(j*sizeof(char *));
  537. X     for (i = 0; i < j; i++) {
  538. X         set_other_field(i,newentry,otherdata[i]);
  539. X     }
  540. X  }
  541. X  else newentry -> other_fields = 0;
  542. X  return(newlink);
  543. X}  
  544. X  
  545. X
  546. Xother_fields () 
  547. X{
  548. X  int rval;
  549. X  rval = rolo_menu_yes_no (
  550. X             "Additional fields? ",DEFAULT_NO,1,
  551. X             MOREFIELDSHELP, "additional fields"
  552. X          );
  553. X  return(rval == MENU_YES);
  554. X}
  555. X
  556. X
  557. Xadd_the_entry ()
  558. X{
  559. X  return(MENU_YES == rolo_menu_yes_no (
  560. X              "Add new entry to rolodex? ",DEFAULT_YES,1,
  561. X              NEWADDHELP, "adding newly entered entry"
  562. X           ));
  563. X}
  564. X
  565. X
  566. Xrolo_add () 
  567. X
  568. X{
  569. X  int i,j,k,rval,menuval;
  570. X  char *response;
  571. X  char *basicdata[N_BASIC_FIELDS], *otherdata[100];
  572. X  Ptr_Rolo_List rlink;
  573. X
  574. X  if(read_only)
  575. X  {
  576. X    printf("Readonly mode: cannot add entries.\n");
  577. X    sleep(2);
  578. X    return(1);
  579. X  }
  580. X        
  581. X  for (j = 0; j < 100; j++) otherdata[j] = (char *)NULL;
  582. X  for (j = 0; j < N_BASIC_FIELDS; j++) basicdata[j] = (char *)NULL;
  583. X  cathelpfile(ADDINFO,(char *)NULL,1);
  584. X  
  585. X  /* 'k' and 'kludge' are are kludge to allow us to back up from entering */
  586. X  /* user defined fields to go an correct wrong basic field information. */
  587. X  
  588. X  k = 0;
  589. X  
  590. X  kludge :
  591. X  
  592. X  for (j = k; j < N_BASIC_FIELDS - 1; j++) {
  593. X        
  594. X      redo :
  595. X        
  596. X      rval = menu_match (
  597. X           &menuval,&response,
  598. X           Field_Names[j],
  599. X           0,0,0,1,5,
  600. X           "\\",A_ABORT_ADD,
  601. X           "^",A_BACKUP,
  602. X           "!",A_FILL_IN_REST,
  603. X           "?",A_HELP,
  604. X           "",A_NO_DATA
  605. X        );
  606. X        
  607. X      switch (rval) {
  608. X        
  609. X        case MENU_NO_MATCH :
  610. X          basicdata[j] = copystr(response);
  611. X          if (j == 0 && strlen(basicdata[j]) == 0) {
  612. X             printf("Each entry must have a name!\n\n");
  613. X         sleep(2);
  614. X             goto redo;
  615. X          }
  616. X          break;
  617. X
  618. X        case MENU_MATCH :
  619. X          switch (menuval) {
  620. X            case A_BACKUP :
  621. X              if (j == 0) return(0);
  622. X              j--;
  623. X              goto redo;
  624. X              /* break; */
  625. X            case A_ABORT_ADD :
  626. X              return(0);
  627. X              /* break; */
  628. X            case A_FILL_IN_REST :
  629. X              if (j == 0) {
  630. X                 fprintf(stderr,"You must enter at least a name...\n\n");
  631. X         sleep(2);
  632. X                 goto redo;
  633. X              }
  634. X              goto add_entry;
  635. X              /* break; */
  636. X            case A_HELP :
  637. X              cathelpfile(ADDHELP,"adding entries",1);
  638. X              any_char_to_continue();
  639. X              clear_the_screen();
  640. X              cathelpfile(ADDINFO,(char *)NULL,0);
  641. X              for (i = 0; i < j; i++) {
  642. X                  printf("%s%s\n",Field_Names[i],basicdata[i]);
  643. X              }
  644. X              goto redo;                            
  645. X              /* break; */
  646. X            case A_NO_DATA :
  647. X              if (j == 0) {
  648. X                 fprintf(stderr,"You must enter at least a name...\n\n");
  649. X         sleep(2);
  650. X                 goto redo;
  651. X              }
  652. X
  653. X              if (basicdata[j] != (char *)NULL)
  654. X            basicdata[j][0] = '\0';
  655. X          else
  656. X            basicdata[j] = "";
  657. X              break;
  658. X            default :
  659. X              fprintf(stderr,"Impossible rval from rolo_add menu_match\n\n");
  660. X              save_and_exit(-1);
  661. X              break;
  662. X          }
  663. X          break;
  664. X
  665. X        case MENU_EOF :
  666. X          user_eof();
  667. X          break;
  668. X          
  669. X        case MENU_ERROR :
  670. X        case MENU_AMBIGUOUS :
  671. X        default :
  672. X          fprintf(stderr,"Impossible return from rolo_add menu_match\n");
  673. X          save_and_exit(-1);
  674. X          break;
  675. X
  676. X      }
  677. X
  678. X  }
  679. X
  680. X  if (other_fields()) {
  681. X     for (j = 0; j < 100; j++) {
  682. X         redo_other :
  683. X         rval = menu_match (
  684. X              &menuval,&response,
  685. X              "Enter <name>: <data> (type RETURN to quit) : ",
  686. X              0,0,0,0,5,
  687. X              "\\",O_ABORT,
  688. X              "?",O_HELP,
  689. X              "Help",O_HELP,
  690. X              "^",O_BACKUP,
  691. X              "",O_DONE_OTHERS
  692. X           );
  693. X         switch (rval) {
  694. X           case MENU_MATCH :
  695. X             switch (menuval) {
  696. X               case O_DONE_OTHERS :
  697. X                 goto add_entry;
  698. X                 /* break; */
  699. X               case O_BACKUP :
  700. X                 if (j == 0) {
  701. X                    k = N_BASIC_FIELDS - 2;
  702. X                    goto kludge;
  703. X                 }
  704. X                 else {
  705. X                    j--;
  706. X                    printf("Deleting %s\n",otherdata[j]);
  707. X                    goto redo_other;
  708. X                 }
  709. X                 /* break; */
  710. X               case O_ABORT :
  711. X                 return(0);
  712. X                 /* break; */
  713. X               case O_HELP :
  714. X                 cathelpfile(OTHERFORMATHELP,"user-item format",1);
  715. X                 any_char_to_continue();
  716. X                 goto redo_other;
  717. X              }   
  718. X             break;
  719. X           case MENU_NO_MATCH :
  720. X             if ((index(response,':') == (char *)NULL) ||
  721. X         (*response == ':')) {
  722. X                printf("No field name provided -- separate with a ':'.\n");
  723. X                goto redo_other;
  724. X             }
  725. X             otherdata[j] = copystr(response);
  726. X             break;
  727. X           case MENU_EOF :
  728. X             user_eof();
  729. X             break;
  730. X           case MENU_AMBIGUOUS :
  731. X           case MENU_ERROR :
  732. X           default :
  733. X             fprintf(stderr,"Impossible rval from add_other menu_match\n");
  734. X             save_and_exit(-1);
  735. X         }
  736. X     }
  737. X  }
  738. X
  739. X  add_entry :   
  740. X
  741. X  basicdata[N_BASIC_FIELDS - 1] = timestring();
  742. X  
  743. X  rlink = create_entry(basicdata,otherdata);
  744. X  clear_the_screen();
  745. X  display_entry(get_entry(rlink));
  746. X  if (add_the_entry()) {
  747. X     printf (
  748. X         "Adding entry for %s to rolodex\n",
  749. X         get_basic_rolo_field((int) R_NAME,get_entry(rlink))
  750. X      );
  751. X     rolo_insert(rlink,compare_links);
  752. X     changed = 1;
  753. X     sleep(2);
  754. X  }
  755. X  else {
  756. X     return(0);
  757. X  }
  758. X  return(0);    /* Should never hit this... */
  759. X}
  760. X
  761. X
  762. Xentry_action (rlink) Ptr_Rolo_List rlink;
  763. X
  764. X{
  765. X  static entry_menu_displayed = 0;
  766. X  int rval,menuval;
  767. X  char *response;
  768. X  
  769. X  if (!entry_menu_displayed) cathelpfile(ENTRYMENU,(char *)NULL,0);
  770. X#ifdef NEVERDEF
  771. X  entry_menu_displayed = 1;    /* This may be turned off to provide verbose help */
  772. X#endif
  773. X
  774. X  redo :
  775. X  
  776. X  rval = menu_match (
  777. X       &menuval, &response,
  778. X       "Action (? for help) : ",
  779. X       0,1,1,1,7,
  780. X       "\\",E_ABORT,
  781. X       "?",E_HELP,
  782. X       "",E_CONTINUE,
  783. X       "-",E_DELETE,
  784. X       "+",E_UPDATE,
  785. X       "<",E_PREV,
  786. X       "%",E_SCAN
  787. X    );
  788. X    
  789. X  if (rval != MENU_MATCH) {
  790. X     if (rval == MENU_EOF) user_eof();
  791. X     fprintf(stderr,"Impossible return from entry_action menu_match\n");
  792. X     save_and_exit(-1);
  793. X  }
  794. X
  795. X  switch (menuval) {
  796. X    case E_ABORT :
  797. X    case E_CONTINUE :
  798. X    case E_PREV :
  799. X      break;
  800. X    case E_SCAN :
  801. X      rolo_peruse_mode(get_next_link(rlink));
  802. X      break;
  803. X    case E_UPDATE :
  804. X      rolo_update_mode(rlink);
  805. X      break;
  806. X    case E_DELETE :
  807. X      if(!rolo_delete(rlink))
  808. X          printf("Entry deleted\n");
  809. X      sleep(1);
  810. X      changed = 1;
  811. X      break;
  812. X    case E_HELP :
  813. X      cathelpfile (
  814. X          (in_search_mode ? ESEARCHHELP : ESCANHELP),
  815. X          "entry actions",
  816. X          1
  817. X       );
  818. X      any_char_to_continue();
  819. X      clear_the_screen();
  820. X      display_entry(get_entry(rlink));
  821. X      goto redo;
  822. X      /* break; */
  823. X    default :
  824. X      fprintf(stderr,"Impossible menuval in entry_action\n");
  825. X      save_and_exit(-1);
  826. X  }
  827. X
  828. X  return(menuval);
  829. X  
  830. X}
  831. X
  832. X
  833. Xdisplay_list_of_entries (rlist) Ptr_Rolo_List rlist;
  834. X
  835. X{
  836. X  Ptr_Rolo_List old,hold;
  837. X
  838. X  if(rlist != 0)
  839. X    hold = get_next_link(rlist);    /* In case of change */
  840. X        
  841. X  while (rlist != 0) {        
  842. X    
  843. X    if (!get_matched(rlist)) goto next;
  844. X        
  845. X    loop :    
  846. X
  847. X    display_entry(get_entry(rlist));
  848. X    
  849. X    switch (entry_action(rlist)) {
  850. X      case E_CONTINUE :
  851. X        break;
  852. X      case E_ABORT :
  853. X        return(0);
  854. X        /* break; */
  855. X      case E_PREV :
  856. X        old = rlist;
  857. X        find_prev_match :
  858. X        if (get_prev_link(rlist) == 0) {
  859. X           rlist = old;
  860. X           printf("No previous entry in scan list\n");
  861. X           sleep(2);
  862. X        }
  863. X        else {
  864. X           rlist = get_prev_link(rlist);
  865. X           if (!get_matched(rlist)) goto find_prev_match;
  866. X        }
  867. X        goto loop;
  868. X        /* break; */
  869. X      case E_UPDATE :
  870. X    if(name_changed)
  871. X    {
  872. X        printf("Continuing scan at next entry in scan list before change...\n");    
  873. X        sleep(1);
  874. X         rlist = hold;
  875. X
  876. X        break;
  877. X    }
  878. X    /* Deliberate fall-thru */
  879. X      default :
  880. X        printf("Displaying next entry in scan list...\n");
  881. X        sleep(1);
  882. X        break;
  883. X    }
  884. X    
  885. X    next :
  886. X    
  887. X    if(!name_changed)
  888. X        rlist = get_next_link(rlist);
  889. X    else
  890. X    name_changed = 0;
  891. X
  892. X    if(rlist != 0)
  893. X    hold = get_next_link(rlist);    /* In case of change */
  894. X    
  895. X  }
  896. X  
  897. X  printf("No further entries to scan...\n");
  898. X  sleep(2);     
  899. X  return(0);
  900. X}
  901. X  
  902. X
  903. Xrolo_peruse_mode (first_rlink) Ptr_Rolo_List first_rlink;
  904. X
  905. X{
  906. X  Ptr_Rolo_List rlist = first_rlink;
  907. X  if (0 == Begin_Rlist) {
  908. X     fprintf(stderr,"No further entries in rolodex...\n");
  909. X     sleep(2);
  910. X     return(0);
  911. X  }
  912. X  while (rlist != 0) {  
  913. X    set_matched(rlist);
  914. X    rlist = get_next_link(rlist);
  915. X  }    
  916. X  display_list_of_entries(first_rlink);
  917. X  rlist = first_rlink;
  918. X  while (rlist != 0) {  
  919. X    unset_matched(rlist);
  920. X    rlist = get_next_link(rlist);
  921. X  }    
  922. X
  923. X  return(0);
  924. X}
  925. END_OF_FILE
  926. if test 9950 -ne `wc -c <'./operatns.c'`; then
  927.     echo shar: \"'./operatns.c'\" unpacked with wrong size!
  928. fi
  929. # end of './operatns.c'
  930. fi
  931. if test -f './rolo.c' -a "${1}" != "-c" ; then 
  932.   echo shar: Will not clobber existing file \"'./rolo.c'\"
  933. else
  934. echo shar: Extracting \"'./rolo.c'\" \(18313 characters\)
  935. sed "s/^X//" >'./rolo.c' <<'END_OF_FILE'
  936. X/* rolo.c */
  937. X#ifdef UNIX
  938. X#include <sys/types.h>
  939. X#include <sys/stat.h>
  940. X#include <pwd.h>
  941. X#include <string.h>
  942. X#ifdef BSD
  943. X#include <sys/file.h>
  944. X#else
  945. X#include <fcntl.h>
  946. X#endif
  947. X#endif
  948. X
  949. X#ifdef VMS
  950. X#include <types.h>
  951. X#include <file.h>
  952. X#include <stat.h>
  953. X#include <string.h>
  954. X#endif
  955. X
  956. X#ifdef MSDOS
  957. X#include <fcntl.h>
  958. X#    ifdef MSC
  959. X#    include <sys    ypes.h>
  960. X#    endif    /* MSC */
  961. X#include <sys/stat.h>
  962. X#include <errno.h>
  963. X#include <string.h>
  964. X#endif
  965. X
  966. X#include <stdio.h>
  967. X#include <ctype.h>
  968. X/* #include <sgtty.h> */
  969. X#include <signal.h>
  970. X
  971. X
  972. X#ifdef TMC
  973. X#include <ctools.h>
  974. X#else
  975. X#include "ctools.h"
  976. X#endif
  977. X#include "args.h"
  978. X#include "menu.h"
  979. X#include "mem.h"
  980. X
  981. X#include "rolofilz.h"
  982. X#include "rolodefs.h"
  983. X#include "datadef.h"
  984. X
  985. X#ifndef BSD
  986. X/* BSD Unix gives us these values but AT&T Unix, VMS and MSDOS don't */
  987. X/* Used with 'access(2)' syscall */
  988. X#define R_OK 04
  989. X#define F_OK 00
  990. X#define W_OK 02
  991. X#endif
  992. X
  993. X#ifdef UNIX
  994. X#define    DEF_PERM 0600    /* Default permissions: All, for owner only */
  995. X#endif
  996. X
  997. X#ifdef VMS
  998. X#define    DEF_PERM 0600    /* Default permissions: All, for owner only */
  999. X#endif
  1000. X
  1001. X#ifdef MSDOS
  1002. X#define    DEF_PERM (S_IREAD | S_IWRITE)    /* Default permissions: All */
  1003. X#endif
  1004. X
  1005. X#define MAX_LINES    60        /* Max number of lines/page */
  1006. X
  1007. Xstatic struct stat stat_buf;
  1008. X
  1009. Xstatic char rolodir[DIRPATHLEN];        /* directory where rolo data is */
  1010. Xstatic char filebuf[DIRPATHLEN];        /* stores result of homedir() */
  1011. X
  1012. Xint changed = 0;
  1013. Xint name_changed = 0;
  1014. Xint reorder_file = 0;
  1015. Xint rololocked = 0;
  1016. Xint in_search_mode = 0;
  1017. Xint read_only = 0;
  1018. X
  1019. Xchar *rolo_emalloc (size) int size;
  1020. X
  1021. X/* error handling memory allocator */
  1022. X
  1023. X{
  1024. X  char *rval;        
  1025. X  char *malloc();
  1026. X  if (0 == (rval = malloc((unsigned)size))) {        
  1027. X     fprintf(stderr,"Fatal error:  out of memory\n");
  1028. X     save_and_exit(-1);                                               
  1029. X  }
  1030. X  return(rval);
  1031. X}  
  1032. X
  1033. X        
  1034. Xchar *copystr (s) char *s;
  1035. X
  1036. X/* memory allocating string copy routine */
  1037. X
  1038. X
  1039. X{
  1040. X char *copy;        
  1041. X if (s == 0) return(0);
  1042. X copy = rolo_emalloc(strlen(s) + 1);
  1043. X strcpy(copy,s);
  1044. X return(copy);
  1045. X}
  1046. X
  1047. Xchar *timestring ()
  1048. X
  1049. X/* returns a string timestamp */
  1050. X
  1051. X{
  1052. X  char *s;        
  1053. X  long timeval;
  1054. X  long time();
  1055. X
  1056. X  time(&timeval);
  1057. X  s = ctime(&timeval);  
  1058. X  s[strlen(s) - 1] = '\0';
  1059. X  return(copystr(s));
  1060. X}  
  1061. X  
  1062. X
  1063. Xuser_interrupt ()
  1064. X
  1065. X/* if the user hits C-C (we assume he does it deliberately) */
  1066. X
  1067. X{
  1068. X#ifdef VMS
  1069. X  delete(homedir(ROLOLOCK));
  1070. X  delete(homedir(ROLOTEMP));
  1071. X#else
  1072. X  unlink(homedir(ROLOLOCK));
  1073. X  unlink(homedir(ROLOTEMP));
  1074. X#endif
  1075. X  fprintf(stderr,"\nAborting rolodex, no changes since last save recorded\n");
  1076. X  exit(-1);  
  1077. X}  
  1078. X
  1079. X
  1080. Xuser_eof ()
  1081. X
  1082. X/* if the user hits C-D */
  1083. X
  1084. X{
  1085. X#ifdef VMS
  1086. X  delete(homedir(ROLOLOCK));
  1087. X#else
  1088. X  unlink(homedir(ROLOLOCK));        
  1089. X#endif
  1090. X  fprintf(stderr,"\nUnexpected EOF on terminal. Saving rolodex and exiting\n");
  1091. X  save_and_exit(-1);        
  1092. X}
  1093. X
  1094. X
  1095. Xroloexit (rval) int rval;
  1096. X{
  1097. X  /* In case it hasn't been cleaned up, also clobber ROLOTEMP. */
  1098. X  clear_the_screen();
  1099. X  if (rololocked)
  1100. X#ifdef VMS
  1101. X  delete(homedir(ROLOTEMP));
  1102. X  delete(homedir(ROLOLOCK));
  1103. X  exit(rval==0?1:rval);
  1104. X#else
  1105. X  unlink(homedir(ROLOTEMP));
  1106. X  unlink(homedir(ROLOLOCK));
  1107. X  exit(rval);
  1108. X#endif
  1109. X}  
  1110. X      
  1111. X                                      
  1112. Xsave_to_disk ()
  1113. X
  1114. X/* move the old rolodex to a backup, and write out the new rolodex and */
  1115. X/* a copy of the new rolodex (just for safety) */
  1116. X
  1117. X{
  1118. X  FILE *tempfp,*copyfp;        
  1119. X  char *strcpy();
  1120. X  char d1[DIRPATHLEN], d2[DIRPATHLEN];
  1121. X
  1122. X#ifdef VMS
  1123. X  /*
  1124. X   * Since VMS keeps versions of files around, clobber any that are still
  1125. X   * hanging around.  If appropriate access permissions aren't granted,
  1126. X   * well, they'll just have to purge their directory...
  1127. X   */
  1128. X  delete(homedir(ROLOTEMP));    /* There will be a copy of this from earlier */
  1129. X
  1130. X  if(!access(homedir(ROLOCOPY),R_OK))
  1131. X    if(!access(homedir(ROLOCOPY),W_OK))    /* Implies delete permission */
  1132. X    delete(homedir(ROLOCOPY));
  1133. X#endif
  1134. X  tempfp = fopen(homedir(ROLOTEMP),"w");
  1135. X  if(tempfp == (FILE *)NULL)
  1136. X     perror(ROLOTEMP);
  1137. X
  1138. X  copyfp = fopen(homedir(ROLOCOPY),"w");
  1139. X  if(copyfp == (FILE *)NULL)
  1140. X     perror(ROLOCOPY);
  1141. X
  1142. X  if (tempfp == (FILE *)NULL || copyfp == (FILE *)NULL) {
  1143. X     fprintf(stderr,"Unable to write rolodex...\n");
  1144. X     fprintf(stderr,"Any changes made have not been recorded\n");
  1145. X     roloexit(-1);
  1146. X  }
  1147. X
  1148. X  /*
  1149. X   * Be sure to set proper permissions on the temp,copy files *before* putting
  1150. X   * data in them...
  1151. X   */
  1152. X#ifndef MSDOS
  1153. X  if(chmod(homedir(ROLOTEMP),(int)stat_buf.st_mode))
  1154. X    fprintf(stderr,"WARNING: Couldn't set permissions on %s\n",
  1155. X        homedir(ROLOTEMP));
  1156. X
  1157. X  if(chmod(homedir(ROLOCOPY),(int)stat_buf.st_mode))
  1158. X    fprintf(stderr,"WARNING: Couldn't set permissions on %s\n",
  1159. X        homedir(ROLOCOPY));
  1160. X#endif    /* MSDOS */
  1161. X
  1162. X  write_rolo(tempfp,copyfp);
  1163. X  
  1164. X  fclose(tempfp);    
  1165. X  fclose(copyfp);
  1166. X
  1167. X#ifdef UNIX
  1168. X  unlink(strcpy(d1,homedir(ROLOBAK)));              
  1169. X  link(strcpy(d1,homedir(ROLODATA)),strcpy(d2,homedir(ROLOBAK)));
  1170. X  unlink(strcpy(d1,homedir(ROLODATA)));
  1171. X
  1172. X  if(link(strcpy(d1,homedir(ROLOTEMP)),strcpy(d2,homedir(ROLODATA))))
  1173. X  {
  1174. X        fprintf(stderr,"Link failed.  Revised rolodex is in %s\n",ROLOCOPY);
  1175. X    roloexit(-1);
  1176. X  }else
  1177. X  {
  1178. X       unlink(strcpy(d1,homedir(ROLOTEMP)));
  1179. X       unlink(strcpy(d1,homedir(ROLOCOPY)));
  1180. X  }
  1181. X#endif
  1182. X
  1183. X#ifdef VMS
  1184. X  delete(homedir(ROLOBAK));
  1185. X
  1186. X  if ((rename(strcpy(d1,homedir(ROLODATA)),strcpy(d2,homedir(ROLOBAK))) != 1) ||
  1187. X      (rename(strcpy(d1,homedir(ROLOTEMP)),strcpy(d2,homedir(ROLODATA)))) != 1) {
  1188. X     fprintf(stderr,"Rename failed.  Revised rolodex is in %s\n",ROLOCOPY);
  1189. X     roloexit(-1);
  1190. X  }else
  1191. X    delete(homedir(ROLOCOPY));    /* Don't really need this anymore */
  1192. X#endif
  1193. X
  1194. X#ifdef MSDOS
  1195. X  unlink(homedir(ROLOBAK));
  1196. X
  1197. X  if (rename(strcpy(d1,homedir(ROLODATA)),strcpy(d2,homedir(ROLOBAK))) ||
  1198. X      rename(strcpy(d1,homedir(ROLOTEMP)),strcpy(d2,homedir(ROLODATA)))) {
  1199. X     fprintf(stderr,"Rename failed.  Revised rolodex is in %s\n",ROLOCOPY);
  1200. X     perror(homedir(ROLODATA));
  1201. X     perror(homedir(ROLOBAK));
  1202. X     perror(homedir(ROLOTEMP));
  1203. X     roloexit(-1);
  1204. X  }else
  1205. X    unlink(homedir(ROLOCOPY));    /* Don't really need this anymore */
  1206. X#endif
  1207. X
  1208. X  printf("Rolodex saved\n");
  1209. X
  1210. X  sleep(1);
  1211. X  changed = 0;
  1212. X  name_changed = 0;
  1213. X}
  1214. X                   
  1215. X
  1216. Xsave_and_exit (rval) int rval;
  1217. X{
  1218. X  if (changed)
  1219. X    save_to_disk();
  1220. X  else
  1221. X#ifdef VMS
  1222. X    delete(homedir(ROLOTEMP));
  1223. X#endif
  1224. X#ifdef UNIX
  1225. X    unlink(homedir(ROLOTEMP));
  1226. X#endif
  1227. X#ifdef MSDOS
  1228. X    unlink(homedir(ROLOTEMP));
  1229. X#endif
  1230. X
  1231. X  roloexit(rval);        
  1232. X}
  1233. X                 
  1234. X#ifdef UNIX
  1235. Xextern struct passwd *getpwnam();
  1236. X
  1237. Xchar *home_directory (name) char *name;
  1238. X{
  1239. X  struct passwd *pwentry;
  1240. X  if (0 == (pwentry = getpwnam(name))) return("");
  1241. X  return(pwentry -> pw_dir);
  1242. X}
  1243. X#endif
  1244. X
  1245. X#ifdef VMS
  1246. X/*
  1247. X * This routine should never be called in VMS.
  1248. X */
  1249. Xchar *home_directory(name) char *name;
  1250. X{
  1251. X    fprintf(stderr,"INTERNAL ERROR: Called home_directory under VMS.\n");
  1252. X    exit(0);
  1253. X}
  1254. X#endif
  1255. X
  1256. X#ifdef MSDOS
  1257. X/*
  1258. X * This is rather simplistic. For drives A through C, try to find a directory
  1259. X * named 'name' under the root.  If not found on any of the drives, then
  1260. X * simply return the root directory of the current drive.
  1261. X */
  1262. Xchar *home_directory (name) char *name;
  1263. X{
  1264. X    char *drvspec = "A:\\";
  1265. X
  1266. X    static char dirbuff[128];
  1267. X    int fid;
  1268. X
  1269. X    for(;*drvspec <= 'C';(*drvspec)++)
  1270. X    {
  1271. X        strcpy(dirbuff,drvspec);
  1272. X        strcat(dirbuff,name);
  1273. X        
  1274. X        if((fid = open(dirbuff,O_RDONLY)) >= 0)
  1275. X        {
  1276. X            close(fid);
  1277. X            return(dirbuff);
  1278. X        }else
  1279. X            if(errno != ENOENT && errno != ENODEV)
  1280. X                return(dirbuff);
  1281. X    }
  1282. X
  1283. X          return("/");
  1284. X}                       
  1285. X#endif
  1286. X
  1287. Xchar *homedir (filename) char *filename;
  1288. X
  1289. X/* e.g., given "rolodex.dat", create "/u/massar/rolodex.dat" */
  1290. X/* rolodir generally the user's home directory but could be someone else's */
  1291. X/* home directory if the -u option is used. */
  1292. X
  1293. X{
  1294. X#ifdef UNIX
  1295. X  nbuffconcat(filebuf,3,rolodir,"/",filename);
  1296. X#endif
  1297. X
  1298. X#ifdef MSDOS
  1299. X  nbuffconcat(filebuf,3,rolodir,"\\",filename);
  1300. X#endif
  1301. X
  1302. X#ifdef VMS
  1303. X  nbuffconcat(filebuf,2,rolodir,filename);
  1304. X#endif
  1305. X
  1306. X  return(filebuf);
  1307. X}
  1308. X
  1309. X
  1310. Xchar *libdir (filename) char *filename;
  1311. X
  1312. X/* return a full pathname into the rolodex library directory */
  1313. X/* the string must be copied if it is to be saved! */
  1314. X
  1315. X{
  1316. X#ifdef UNIX
  1317. X  nbuffconcat(filebuf,3,ROLOLIB,"/",filename);
  1318. X#endif
  1319. X
  1320. X#ifdef MSDOS
  1321. X  /*
  1322. X   * If there's no drive specifier in ROLOLIB, then prepend the current
  1323. X   * drive.
  1324. X   */
  1325. X  char *curdir;
  1326. X  char *getcwd();
  1327. X
  1328. X  curdir = ROLOLIB;
  1329. X
  1330. X  if(curdir[2] != ':')
  1331. X  {
  1332. X      curdir = getcwd((char *)NULL,128);
  1333. X    curdir[3] = '\0';
  1334. X    nbuffconcat(filebuf,4,curdir,ROLOLIB,"\\",filename);
  1335. X    (void)free(curdir);
  1336. X  }else
  1337. X    nbuffconcat(filebuf,3,ROLOLIB,"\\",filename);
  1338. X#endif
  1339. X
  1340. X#ifdef VMS
  1341. X  nbuffconcat(filebuf,2,ROLOLIB,filename);
  1342. X#endif
  1343. X
  1344. X                 
  1345. X  return(filebuf);        
  1346. X}
  1347. X
  1348. X
  1349. Xrolo_only_to_read () 
  1350. X{
  1351. X  return((option_present(READONLYFLAG) << 1) |
  1352. X    (option_present(SUMMARYFLAG) || n_non_option_args()));
  1353. X}
  1354. X
  1355. X
  1356. Xlocked_action () 
  1357. X{
  1358. X  if (option_present(OTHERUSERFLAG)) {        
  1359. X     fprintf(stderr,"Someone else is modifying that rolodex, sorry\n");
  1360. X     exit(-1);
  1361. X  }
  1362. X  else {
  1363. X     cathelpfile(LOCKINFO,"locked rolodex",0);
  1364. X     exit(-1);
  1365. X  }
  1366. X}  
  1367. X  
  1368. X
  1369. Xpretty_print()
  1370. X{
  1371. X    int elt_lines, index, tmp_line_cnt;
  1372. X    int line_cnt = 0;
  1373. X    char *tmpptr;
  1374. X    char *strchr();
  1375. X    FILE *lstfp;
  1376. X    Ptr_Rolo_List rptr;
  1377. X    Ptr_Rolo_Entry lentry;
  1378. X
  1379. X    clear_the_screen();
  1380. X
  1381. X    fputs("\nPretty printing the Rolodex...\n",stdout);
  1382. X    fprintf(stdout,"Print the file %-30s\n", homedir(ROLOPRINT));
  1383. X
  1384. X    lstfp = fopen(homedir(ROLOPRINT),"w");
  1385. X    if(lstfp == (FILE *)NULL) {
  1386. X        perror(homedir(ROLOPRINT));
  1387. X        return;
  1388. X    }
  1389. X
  1390. X    rptr = Begin_Rlist;
  1391. X    if(rptr == 0) {
  1392. X        fputs("\n\nNo entries to print...\n",stderr);
  1393. X        return;
  1394. X    }
  1395. X
  1396. X    while (rptr != 0) {
  1397. X          lentry = get_entry(rptr);
  1398. X
  1399. X        /* Find the number of lines this entry requires to print */
  1400. X        for(elt_lines = 0, index = 0; index < N_BASIC_FIELDS; index++) {
  1401. X            tmpptr = lentry->basicfields[index];
  1402. X            elt_lines++;    /* Even one for an empty line */
  1403. X
  1404. X            while((tmpptr = strchr(tmpptr,';')) != (char *)NULL) {
  1405. X                elt_lines++;
  1406. X                tmpptr++;
  1407. X            }
  1408. X        }
  1409. X        if(lentry->n_others) {
  1410. X            for(index=0; index < lentry->n_others; index++) {
  1411. X                elt_lines++;    /* As above, even if the entry is empty... */
  1412. X                tmpptr = lentry->other_fields[index];
  1413. X                            
  1414. X                            while((tmpptr = strchr(tmpptr,';')) != (char *)NULL) {
  1415. X                                elt_lines++;
  1416. X                                tmpptr++;
  1417. X                            }
  1418. X            }
  1419. X        }
  1420. X
  1421. X        /*
  1422. X         * Check to see if there is enough room on the current page
  1423. X         * to print this entry... Otherwise advance to the top of the
  1424. X         * next page
  1425. X         */
  1426. X        tmp_line_cnt = line_cnt + elt_lines;
  1427. X        if(tmp_line_cnt > MAX_LINES) {
  1428. X            fputc('\f',lstfp);
  1429. X            line_cnt = 0;
  1430. X        }
  1431. X
  1432. X        /*
  1433. X         * We can now start the printing of the actual entry
  1434. X         */
  1435. X        fputs("Name:               ",lstfp);
  1436. X        prt_dump(get_basic_rolo_field((int)R_NAME,lentry),lstfp,20);
  1437. X        fputs("Home address:       ",lstfp);
  1438. X        prt_dump(get_basic_rolo_field((int)R_HOME_ADDRESS,lentry),lstfp,20);
  1439. X        fputs("Home phone:         ",lstfp);
  1440. X        prt_dump(get_basic_rolo_field((int)R_HOME_PHONE,lentry),lstfp,20);
  1441. X        fputs("Company:            ",lstfp);
  1442. X        prt_dump(get_basic_rolo_field((int)R_COMPANY,lentry),lstfp,20);
  1443. X        fputs("Work address:       ",lstfp);
  1444. X        prt_dump(get_basic_rolo_field((int)R_WORK_ADDRESS,lentry),lstfp,20);
  1445. X        fputs("Work phone:         ",lstfp);
  1446. X        prt_dump(get_basic_rolo_field((int)R_WORK_PHONE,lentry),lstfp,20);
  1447. X        fputs("Remarks:            ",lstfp);
  1448. X        prt_dump(get_basic_rolo_field((int)R_REMARKS,lentry),lstfp,20);
  1449. X
  1450. X        /* Now print any user defined fields */
  1451. X        if(lentry->n_others) {
  1452. X            fputs("*** User defined fields ***\n",lstfp);
  1453. X            line_cnt++;
  1454. X            for(index = 0;index < lentry->n_others; index++)
  1455. X                fprintf(lstfp,"%-30s\n",get_other_field(index,lentry));
  1456. X        }
  1457. X
  1458. X        /* Print the date this entry was last updated */
  1459. X        fputs("                LAST UPDATED:       ",lstfp);
  1460. X        prt_dump(get_basic_rolo_field((int)R_UPDATED,lentry),lstfp,20);
  1461. X
  1462. X        /* Print two(2) blank lines, and increment the line count */
  1463. X        fputs("\n\n",lstfp);
  1464. X        line_cnt += elt_lines;
  1465. X        line_cnt += 2;        /* For the two blank lines between entries */
  1466. X        rptr = get_next_link(rptr);
  1467. X    }
  1468. X    fclose(lstfp);
  1469. X}
  1470. X
  1471. Xprt_dump(strptr, stream, offset)
  1472. Xchar *strptr;
  1473. XFILE *stream;
  1474. Xint offset;
  1475. X{
  1476. X    int i;
  1477. X
  1478. X    if(*strptr == (char)NULL)
  1479. X        fputs("<<NONE>>\n",stream);
  1480. X    else {
  1481. X        for(; *strptr != '\0'; strptr++) {
  1482. X            if(*strptr == ';') {
  1483. X                fputc('\n',stream);
  1484. X                for(i = 0; i < offset; i++)
  1485. X                    fputc(' ',stream);
  1486. X            }
  1487. X            else
  1488. X                fputc(*strptr,stream);
  1489. X        }
  1490. X        fputc('\n',stream);
  1491. X    }
  1492. X}
  1493. X
  1494. Xmain (argc,argv) int argc; char *argv[];
  1495. X
  1496. X{
  1497. X    int fd,in_use,rolofd;
  1498. X    Bool not_own_rolodex;        
  1499. X    char *user = "";
  1500. X    FILE *tempfp;
  1501. X    
  1502. X    clearinit();
  1503. X    clear_the_screen();
  1504. X    
  1505. X    /* parse the options and arguments, if any */
  1506. X    
  1507. X    switch (get_args(argc,argv,T,T)) {
  1508. X        case ARG_ERROR : 
  1509. X          roloexit(-1);
  1510. X        case NO_ARGS :
  1511. X          break;
  1512. X        case ARGS_PRESENT :
  1513. X          if (ALL_LEGAL != legal_options(LEGAL_OPTIONS)) {
  1514. X                fprintf(stderr,"illegal option\nusage: %s\n",USAGE);
  1515. X                roloexit(-1);
  1516. X          }
  1517. X    }
  1518. X    
  1519. X    /* find the directory in which the rolodex file we want to use is */
  1520. X    
  1521. X    not_own_rolodex = option_present(OTHERUSERFLAG);        
  1522. X    if (not_own_rolodex) {
  1523. X       if (NIL == (user = option_arg(OTHERUSERFLAG,1)) || 
  1524. X           n_option_args(OTHERUSERFLAG) != 1) {
  1525. X          fprintf(stderr,"Illegal syntax using -u option\nusage: %s\n",USAGE);
  1526. X          roloexit(-1);
  1527. X       }
  1528. X    }        
  1529. X#ifndef MSDOS
  1530. X    else {
  1531. X       if (0 == (user = getenv("HOME"))) {
  1532. X          fprintf(stderr,"Cant find your home directory, no HOME\n");
  1533. X          roloexit(-1);
  1534. X       }
  1535. X    }
  1536. X#endif
  1537. X    if (not_own_rolodex) {
  1538. X#ifndef MSDOS
  1539. X       strcpy(rolodir,user);
  1540. X#else
  1541. X       strcpy(rolodir,home_directory(user));
  1542. X#endif
  1543. X       if (*rolodir == '\0') {
  1544. X          fprintf(stderr,"No user %s is known to the system\n",user);
  1545. X          roloexit(-1);
  1546. X       }
  1547. X    }
  1548. X    else strcpy(rolodir,user);
  1549. X    
  1550. X    /* is the rolodex readable? */
  1551. X    
  1552. X    if (0 != access(homedir(ROLODATA),R_OK)) {
  1553. X        
  1554. X       /* No.  if it exists and we cant read it, that's an error */
  1555. X        
  1556. X       if (0 == access(homedir(ROLODATA),F_OK)) { 
  1557. X          fprintf(stderr,"Cant access rolodex data file to read\n");
  1558. X          roloexit(-1);
  1559. X       }
  1560. X       
  1561. X       /* if it doesn't exist, should we create one? */
  1562. X       /* Under Unix, only if it's our own.  On other systems, it depends.*/
  1563. X
  1564. X#ifdef UNIX       
  1565. X       if (option_present(OTHERUSERFLAG)) {
  1566. X          fprintf(stderr,"No rolodex file belonging to %s found\n",user);
  1567. X          roloexit(-1);
  1568. X       }
  1569. X#endif
  1570. X       /* try to create it, only if its our own */
  1571. X       
  1572. X       if (-1 == (fd = creat(homedir(ROLODATA),DEF_PERM))) {
  1573. X         if(option_present(OTHERUSERFLAG))
  1574. X       fprintf(stderr,"couldn't create rolodex in %s\n",homedir(ROLODATA));
  1575. X     else
  1576. X           fprintf(stderr,"couldn't create rolodex in your home directory\n");
  1577. X
  1578. X         roloexit(-1);
  1579. X       }      
  1580. X       
  1581. X       else {
  1582. X     stat_buf.st_mode = DEF_PERM;    /* For later mode set */
  1583. X         close(fd);
  1584. X         fprintf(stderr,"Creating empty rolodex...\n");
  1585. X       }
  1586. X
  1587. X    }
  1588. X    
  1589. X    /* see if someone else is using it */
  1590. X    
  1591. X    in_use = (0 == access(homedir(ROLOLOCK),F_OK));
  1592. X    
  1593. X    /* are we going to access the rolodex only for reading? */
  1594. X    
  1595. X    if (!(read_only = rolo_only_to_read())) {
  1596. X    
  1597. X       /* No.  Make sure no one else has it locked. */
  1598. X        
  1599. X       if (in_use) {
  1600. X          locked_action();
  1601. X       }
  1602. X        
  1603. X       /* create a lock file.  Catch interrupts so that we can remove */
  1604. X       /* the lock file if the user decides to abort */
  1605. X               
  1606. X       if (!option_present(NOLOCKFLAG)) {
  1607. X          if ((fd = open(homedir(ROLOLOCK),O_EXCL|O_CREAT,00200|00400)) < 0) {
  1608. X             fprintf(stderr,"unable to create lock file...\n");
  1609. X#ifdef VMS
  1610. X         exit(0);
  1611. X#else
  1612. X         exit(1);
  1613. X#endif
  1614. X      }
  1615. X          rololocked = 1;
  1616. X          close(fd);
  1617. X#ifdef MSDOS
  1618. X#    ifdef MSC
  1619. X      signal(SIGINT,user_interupt);
  1620. X#    else
  1621. X      ssignal(SIGINT,user_interrupt);    /* Very Turbo-ish */
  1622. X#    endif    /* MSC */
  1623. X#else
  1624. X          signal(SIGINT,user_interrupt);
  1625. X#endif
  1626. X       }
  1627. X        
  1628. X       /* open a temporary file for writing changes to make sure we can */
  1629. X       /* write into the directory */
  1630. X       
  1631. X       /* when the rolodex is saved, the old rolodex is moved to */
  1632. X       /* a '~' file (on Unix), the temporary is made to be the new rolodex, */
  1633. X       /* and a copy of the new rolodex is made */
  1634. X       
  1635. X       if (NULL == (tempfp = fopen(homedir(ROLOTEMP),"w"))) {
  1636. X           fprintf(stderr,"Can't open temporary file to write to\n");
  1637. X           roloexit(-1);
  1638. X       }        
  1639. X       fclose(tempfp);
  1640. X    
  1641. X    }
  1642. X       
  1643. X    allocate_memory_chunk(CHUNKSIZE);
  1644. X    
  1645. X    if (NULL == (rolofd = open(homedir(ROLODATA),O_RDONLY))) {
  1646. X        fprintf(stderr,"Can't open rolodex data file to read\n");
  1647. X        roloexit(-1);
  1648. X    }
  1649. X    
  1650. X    /* Get the current rolodex file's permissions */
  1651. X    if(fstat(rolofd,&stat_buf))
  1652. X    {
  1653. X    fprintf(stderr,"Can't fstat rolodex data file\n");
  1654. X    roloexit(-1);
  1655. X    }
  1656. X
  1657. X    /* read in the rolodex from disk */
  1658. X    /* It should never be out of order since it is written to disk ordered */
  1659. X    /* but just in case... */
  1660. X    
  1661. X    if (!(read_only & 1)) printf("Reading in rolodex from %s\n",homedir(ROLODATA));
  1662. X    read_rolodex(rolofd);
  1663. X    close(rolofd);
  1664. X    if (!(read_only & 1)) printf("%d entries listed\n",rlength(Begin_Rlist));
  1665. X    if (reorder_file && !read_only) {
  1666. X       fprintf(stderr,"Reordering rolodex...\n");
  1667. X       rolo_reorder();
  1668. X       fprintf(stderr,"Saving reordered rolodex to disk...\n");
  1669. X       save_to_disk();
  1670. X    }
  1671. X       
  1672. X    /* the following routines live in 'options.c' */
  1673. X    
  1674. X    /* -s option.  Prints a short listing of people and phone numbers to */
  1675. X    /* standard output */
  1676. X    
  1677. X    if (option_present(SUMMARYFLAG)) {
  1678. X        print_short();
  1679. X#ifdef VMS
  1680. X        exit(1);
  1681. X#else
  1682. X        exit(0);         
  1683. X#endif 
  1684. X    }
  1685. X    
  1686. X    /* rolo <name1> <name2> ... */
  1687. X    /* print out info about people whose names contain any of the arguments */
  1688. X    
  1689. X    if (n_non_option_args() > 0) {
  1690. X       print_people();
  1691. X#ifdef VMS
  1692. X       exit(1);
  1693. X#else
  1694. X       exit(0);
  1695. X#endif
  1696. X    }
  1697. X    
  1698. X    /* regular rolodex program */
  1699. X    
  1700. X    interactive_rolo();
  1701. X#ifdef VMS
  1702. X    exit(1);
  1703. X#else
  1704. X    exit(0);
  1705. X#endif
  1706. X    
  1707. X}
  1708. X
  1709. X#ifdef MSC
  1710. Xsleep(sec)
  1711. Xint sec;
  1712. X{
  1713. X    register long tloc;
  1714. X    long time();
  1715. X
  1716. X    tloc = time((long *)NULL);
  1717. X
  1718. X    tloc += (long)sec;
  1719. X
  1720. X    while(time((long *)NULL) <= tloc);
  1721. X
  1722. X    return(0);
  1723. X}
  1724. X#endif
  1725. END_OF_FILE
  1726. if test 18313 -ne `wc -c <'./rolo.c'`; then
  1727.     echo shar: \"'./rolo.c'\" unpacked with wrong size!
  1728. fi
  1729. # end of './rolo.c'
  1730. fi
  1731. if test -f './toolsdir/ctools.h' -a "${1}" != "-c" ; then 
  1732.   echo shar: Will not clobber existing file \"'./toolsdir/ctools.h'\"
  1733. else
  1734. echo shar: Extracting \"'./toolsdir/ctools.h'\" \(11422 characters\)
  1735. sed "s/^X//" >'./toolsdir/ctools.h' <<'END_OF_FILE'
  1736. X/* -*- Mode: C; Package: (CTOOLS C) -*- */
  1737. X
  1738. X#ifndef Bool
  1739. X#define Bool int
  1740. X#endif
  1741. X
  1742. X#ifndef T
  1743. X#define T 1
  1744. X#endif
  1745. X
  1746. X#ifndef F
  1747. X#define F 0
  1748. X#endif
  1749. X
  1750. X#ifdef VMS
  1751. X#ifndef MAXINT
  1752. X#define MAXINT 2147483647
  1753. X#define MAXINTSTR "2147483647"
  1754. X#endif
  1755. X#endif
  1756. X
  1757. X#ifdef VMS
  1758. X#ifndef MAXINT
  1759. X#define MAXINT 2147483647
  1760. X#define MAXINTSTR "2147483647"
  1761. X#endif
  1762. X#endif
  1763. X
  1764. X#ifndef MAXPATHLEN
  1765. X#define MAXPATHLEN 80
  1766. X#endif
  1767. X
  1768. Xextern char *emalloc();
  1769. X
  1770. X  /* int space; */
  1771. X  /* space must be greater than 0 */
  1772. X  /* Causes executution to halt with a 'Fatal error' message if memory */
  1773. X  /* cannot be allocated, otherwise returns pointer to malloc-ed space */
  1774. X
  1775. Xextern char *anewstr();
  1776. X
  1777. X  /* char *astring; */
  1778. X  /* emalloc's space and copies astring into that space.  Returns pointer */
  1779. X  /* to new string. */
  1780. X
  1781. X
  1782. Xextern int copy();
  1783. X
  1784. X  /* char *dest, *src; int n; */
  1785. X  /* copies exactly n bytes. */
  1786. X  /* return value undefined.  Use only as procedure. */
  1787. X
  1788. Xextern int fill();
  1789. X
  1790. X  /* char *addr, ch; int n; */
  1791. X  /* copies ch into n consecutive bytes. */
  1792. X  /* return value undefined.  Use only as procedure. */
  1793. X
  1794. Xextern int to_upper_if_lower();
  1795. X
  1796. X  /* char ch;  Returns possibly upper-cased value. */
  1797. X
  1798. Xextern int to_lower_if_upper();
  1799. X
  1800. X  /* char ch;  Returns possibly lower-cased value. */
  1801. X
  1802. Xextern int buffconcat();
  1803. X
  1804. X  /* char *buffer, *s1, *s2; */
  1805. X  /* s1 and s2 must be null terminated.  Buffer must be at least */
  1806. X  /* strlen(s1) + strlen(s2) + 1 characters long.  Buffer is null */
  1807. X  /* terminated upon completion. */
  1808. X
  1809. X  /* return value undefined.  Use only as procedure. */
  1810. X
  1811. Xextern int nbuffconcat();
  1812. X
  1813. X  /* char *buffer; int n; char *s1,*s2,*s3,*s4,*s5,*s6; */
  1814. X  /* all the strings must be null terminated.  Buffer must be big enough */
  1815. X  /* to hold the null terminated result.  0 < n < 7 ..  */
  1816. X  /* returns -1 if n is out of range, otherwise 0 */
  1817. X
  1818. Xextern int slcompare();
  1819. X
  1820. X  /* char *s1; int l1; char *s2; int l2 */
  1821. X  /* does not stop if it encounters a null character. */
  1822. X  /* returns 0 if equal, -1 if not equal */
  1823. X
  1824. Xextern int slge_compare();
  1825. X
  1826. X  /* char *s1; int l1; char *s2; int l2 */
  1827. X  /* does not stop if it encounters a null character. */
  1828. X  /* returns 0 if equal, -1 if s1 < s2, 1 if s1 > s2 */
  1829. X
  1830. Xextern int nocase_compare();
  1831. X
  1832. X  /* char *s1; int l1; char *s2; int l2 */
  1833. X  /* does not stop if it encounters a null character. */
  1834. X  /* returns 0 if equal, -1 if s1 < s2, 1 if s1 > s2  case independently. */
  1835. X
  1836. Xextern char * strfind();
  1837. X
  1838. X  /* char *s1; char *s2; int fast; */
  1839. X  /* finds s2 as a substring of s1.  s1 and s2 are null terminated. */
  1840. X  /* returns 0 if not found, otherwise pointer into s1 to first matching */
  1841. X  /* character. */
  1842. X
  1843. X  /* WARNING:  will access off the end of s1 in the interest of efficiency */
  1844. X  /* if 'fast' is non-zero. */
  1845. X
  1846. Xextern char * strncfind();
  1847. X
  1848. X  /* char *s1; char *s2; int fast; */
  1849. X  /* finds s2 as a substring of s1 case independently.  s1 and s2 are */
  1850. X  /* null terminated. */
  1851. X  /* returns 0 if not found, otherwise pointer into s1 to first matching */
  1852. X  /* character. */
  1853. X
  1854. X  /* WARNING:  will access off the end of s1 in the interest of efficiency */
  1855. X  /* if 'fast' is non-zero. */
  1856. X
  1857. Xextern char * strsearch();
  1858. X
  1859. X  /* char *s1; int l1; char *s2; int l2 */
  1860. X  /* finds s2 as a substring of s1.  Does not stop if it encounters a null. */
  1861. X  /* returns pointer into s1, otherwise (char *) 0 if search fails */
  1862. X  /* case dependent */
  1863. X
  1864. Xextern char * strncsearch();
  1865. X
  1866. X  /* char *s1; int l1; char *s2; int l2 */
  1867. X  /* finds s2 as a substring of s1. */
  1868. X  /* returns pointer into s1, otherwise (char *) 0 if search fails */
  1869. X  /* case independent */
  1870. X
  1871. Xextern int remove_excess_blanks();
  1872. X
  1873. X  /* char *newstring, *oldstring; */
  1874. X  /* newstring must be long enough to hold the result, which may be as */
  1875. X  /* long as oldstring.  oldstring must be null terminated. */
  1876. X  /* an excess blank is any blank before the first non-blank character, */
  1877. X  /* any blank after the last non-blank character, and any blank immediately */
  1878. X  /* following a blank. */
  1879. X  /* returns length of newstring */
  1880. X
  1881. Xextern int yes_or_no_check();
  1882. X
  1883. X  /* char *astring; */
  1884. X  /* returns 1 for yes, 0 for no, -1 for neither. */
  1885. X  /* astring must be one of "YES", "Y", "NO", "N" in any capitalization. */
  1886. X
  1887. X
  1888. X/* These routines return T if every char satisfies a certain condition. */
  1889. X/* These returns all returns T if given a null string. */
  1890. X
  1891. Xextern Bool all_digits();
  1892. Xextern Bool all_whitespace();
  1893. Xextern Bool all_uppercase();
  1894. Xextern Bool all_lowercase();
  1895. Xextern Bool all_alphabetic();
  1896. Xextern Bool all_alphanumeric();
  1897. Xextern Bool all_ascii();
  1898. X
  1899. X
  1900. Xextern int str_to_pos_int();
  1901. X
  1902. X  /* char *astring; int low,high; */
  1903. X  /* low must be >= 0. */
  1904. X  /* returns -1 if *astring is not composed of digits. */
  1905. X  /* returns -2 if the integer is out of range. */
  1906. X  /* despite its name, 0 can be returned as a legitimate value. */
  1907. X  /* treats all digit strings as decimal. */
  1908. X
  1909. X
  1910. Xextern int sreverse();
  1911. X
  1912. X  /* char *buffer; char *astring; */
  1913. X  /* puts the characters of astring in reverse order into buffer. */
  1914. X  /* buffer must be at least as long as astring + 1. */
  1915. X  /* buffer is null terminated when done. */
  1916. X  /* No return value.  Use only as procedure. */
  1917. X
  1918. Xextern char *ip_sreverse();
  1919. X
  1920. X  /* char *astring; */
  1921. X  /* Returns astring with its characters reversed. */
  1922. X  /* reversal is done in place. */
  1923. X
  1924. X
  1925. X
  1926. X#define PATH_MAXPATHLEN 256
  1927. X
  1928. Xchar *temp_path();
  1929. X
  1930. X/*
  1931. X  char *dir; char *filename;
  1932. X
  1933. X  Returns a pointer to a character string containing the string
  1934. X  <dir>/<filename>.  The pointer points to a buffer which will may get
  1935. X  overwritten if any functions in this package are subsequently called.
  1936. X  0 is returned if the pathname would exceed PATH_MAXPATHLEN-1 chars.
  1937. X*/
  1938. X
  1939. X
  1940. Xchar *perm_path();
  1941. X
  1942. X/*
  1943. X  char *dir; char *filename;
  1944. X
  1945. X  Same as temp_path, except the pathname string is malloc'ed and is thus
  1946. X  permanent unless specifically freed by the user.  Further, no limit
  1947. X  on the size of the path is made.
  1948. X*/
  1949. X
  1950. X
  1951. Xchar *make_path();
  1952. X
  1953. X/*
  1954. X  char *dir; char *filename; char *extension; Bool perm;
  1955. X
  1956. X  Creates <dir>/<filename><extension> .  The string returned is permanent
  1957. X  or not depending on 'perm'.  If perm is not true, 0 will be returned if
  1958. X  the resulting path exceeds PATH_MAXPATHLEN-1 chars.
  1959. X*/
  1960. X
  1961. X
  1962. Xchar *make_path_numeric_extension();
  1963. X
  1964. X/*
  1965. X  char *dir; char *filename; int extension; Bool perm;
  1966. X
  1967. X  Same as make_path except that extension is first converted into a
  1968. X  string using sprintf.
  1969. X*/
  1970. X
  1971. X
  1972. Xchar *just_filename();
  1973. X
  1974. X/*  
  1975. X  char *path; Bool new; Bool perm;
  1976. X
  1977. X  Given a path of the form /<x>/<y>/<z> returns <z>.  If new is not set
  1978. X  then a pointer into the original input string is returned.  If new is
  1979. X  set a copy is returned, either permanent or not depending on perm.
  1980. X*/
  1981. X
  1982. X
  1983. X#define ANSWER_NO 0
  1984. X#define ANSWER_YES 1
  1985. X#define ANSWER_HELP 2
  1986. X#define ANSWER_QUIT 3
  1987. X#define ANSWER_EOF 4
  1988. X
  1989. X#define AT_EOF -1
  1990. X#define TOO_MANY_CHARS -2
  1991. X#define IOERROR -3
  1992. X#define TOO_MANY_LINES -4
  1993. X#define LINE_TOO_LONG -5
  1994. X
  1995. Xextern read_yes_or_no ();
  1996. X
  1997. X  /* FILE *iport, *oport; char *prompt; char *helpstring; char *quitstring; */
  1998. X
  1999. X  /* prints prompt, then reads from iport until is gets 'Y', 'N', 'YES' or */
  2000. X  /* 'NO' (case independently).  If helpstring and/or quitstring are not */
  2001. X  /* "" or (char *) 0 then if the user types in one of those ANSWER_HELP */
  2002. X  /* or ANSWER_QUIT are returned, otherwise ANSWER_NO or ANSWER_YES are */
  2003. X  /* eventually returned. */
  2004. X
  2005. X
  2006. Xextern int getline ();
  2007. X
  2008. X  /* FILE *iport; char *buffer; int buflen; */
  2009. X
  2010. X  /* reads a line into buffer.  Does not put the '\n' into buffer. */
  2011. X  /* Returns AT_EOF if at end of file when called.  If it encounters */
  2012. X  /* end of file after reading at least one character, the eof is treated */
  2013. X  /* as if it were a newline.   Returns TOO_MANY_CHARS if more than */
  2014. X  /* buflen - 1 characters are read before encountering a newline. */        
  2015. X  /* In this case exactly buflen - 1 characters are read. */
  2016. X  /* The last character read is always follwed by a '\0'. */
  2017. X  /* if successful getline returns the number of characters read exclusive */
  2018. X  /* of a terminating newline or eof. */
  2019. X
  2020. X
  2021. Xextern int getlines();
  2022. X
  2023. X  /* FILE *fp; int n; char ***ptr_lines; char *linebuf; int maxlinelen; */
  2024. X  /* See documentation for getfile below */
  2025. X  /* If called, 'n' must have a value 0. */
  2026. X
  2027. Xextern int getfile();
  2028. X
  2029. X  /* char *filename; char ***ptr_lines; char *linebuf; int maxlinelen; */
  2030. X
  2031. X  /* read in a file as an array of character strings */
  2032. X  /* 'maxlinelen+1' is the maximum length a line of the file is allowed */
  2033. X  /* to be.  'linebuf' must be at least 'maxlinelen+1' characters long. */
  2034. X  /* Returns the number of lines in the file (and therefore the number */
  2035. X  /* of entries in *ptr_lines) if successful.  Returns IOERROR if it */
  2036. X  /* could not open the file to read from. Returns TOO_MANY_CHARS if */
  2037. X  /* it encounters a line longer than 'maxlinelen' characters.  */
  2038. X
  2039. X  /* Space for each line is malloc'ed as it is read in and the text for */
  2040. X  /* the jth line is stored in (*ptr_lines)[j] */
  2041. X
  2042. X  /* Only works for fairly small files as it recurses its way through the */
  2043. X  /* file and does a lot of malloc-ing.  Use read_file_into_buffer or */
  2044. X  /* ngetfile for large files. */
  2045. X
  2046. Xextern int ngetlines();
  2047. X
  2048. X /* FILE *fp; int n; char ***ptr_lines; char *linebuf; int maxlinelen; */
  2049. X /* Same as getlines, except at most 'n' lines will be read.  Returns */
  2050. X /* TOO_MANY_LINES if more than 'n' lines are present. */
  2051. X
  2052. Xextern int ngetfile();
  2053. X
  2054. X /* int n; char *filename; char ***ptr_lines; char *linebuf; int maxlinelen; */
  2055. X /* See ngetlines above. */
  2056. X
  2057. Xextern int read_file_into_buffer();
  2058. X
  2059. X  /* char *filename; 
  2060. X     char ***ptr_lines;
  2061. X     int maxlines;
  2062. X     char *buffer;
  2063. X     int buflen;
  2064. X     char *linebuffer;
  2065. X     int linebuflen;
  2066. X  */
  2067. X
  2068. X  /* *ptr_lines should be an array of character string pointers maxlines */
  2069. X  /* big.  buffer should be an array of characters buflen long.  The routine */
  2070. X  /* reads lines using getline and stores them into buffer, terminating each */
  2071. X  /* with a null.  A pointer to the nth line read is stored in *ptr_lines[n] */
  2072. X  /* Returns IOERROR if it cannot open the file for reading, TOO_MANY_LINES */
  2073. X  /* if more than maxlines were read in, TOO_MANY_CHARS if buffer is */
  2074. X  /* filled before end of file is reached, and LINE_TOO_LONG is any line is */
  2075. X  /* longer than linebuflen.  Returns number of lines read in if successful. */
  2076. X
  2077. Xextern char *efopen();  
  2078. X
  2079. X  /* char *filename; char *mode */
  2080. X
  2081. X  /* Actually returns a (FILE *), so one must cast the return value to this */
  2082. X  /* type.  It doesn't return a (FILE *) explicitly because then to include */
  2083. X  /* this file one would have to include <stdio.h> explicitly before it. */
  2084. X  /* The routine simply calls fopen with the same arguments, but prints a */
  2085. X  /* reasonable error message and calls exit if the call to fopen fails. */
  2086. X
  2087. X
  2088. Xextern int record_fseek();
  2089. X
  2090. X  /* FILE *fp; long rnum; int fromwhere; int rsize; int hdrsize; */
  2091. X
  2092. X  /* Assumes a file is divided into fixed length records with a fixed length */
  2093. X  /* header (possibly 0 bytes).  Performs a fseek which moves to the start */
  2094. X  /* of a given record.  Record numbers begin with 1. */
  2095. X
  2096. X  /* Returns what fseek returns. */
  2097. X
  2098. X  /* 'rnum' is either relative or absolute, depending on 'fromwhere' which */
  2099. X  /* corresponds to the 'ptrname' argument of fseek. */
  2100. X
  2101. X
  2102. XBool check_string();
  2103. X
  2104. X  /* char *str; long minlen; long maxlen; */
  2105. X
  2106. X  /* Returns T if str is not 0 and has a length between minlen and maxlen */
  2107. X  /* inclusived, otherwise returns F. */
  2108. X
  2109. X
  2110. X#ifndef check_int
  2111. X#define check_int(i,minval,maxval) ((i) >= (minval) && (i) <= (maxval))
  2112. X#endif
  2113. END_OF_FILE
  2114. if test 11422 -ne `wc -c <'./toolsdir/ctools.h'`; then
  2115.     echo shar: \"'./toolsdir/ctools.h'\" unpacked with wrong size!
  2116. fi
  2117. # end of './toolsdir/ctools.h'
  2118. fi
  2119. echo shar: End of archive 3 \(of 4\).
  2120. cp /dev/null ark3isdone
  2121. MISSING=""
  2122. for I in 1 2 3 4 ; do
  2123.     if test ! -f ark${I}isdone ; then
  2124.     MISSING="${MISSING} ${I}"
  2125.     fi
  2126. done
  2127. if test "${MISSING}" = "" ; then
  2128.     echo You have unpacked all 4 archives.
  2129.     rm -f ark[1-9]isdone
  2130. else
  2131.     echo You still need to unpack the following archives:
  2132.     echo "        " ${MISSING}
  2133. fi
  2134. ##  End of shell archive.
  2135. exit 0
  2136.